\section{64 бита}

\subsection{x86-64}
\myindex{x86-64}
\label{x86-64}

Это расширение x86-архитектуры до 64 бит.

С точки зрения начинающего reverse engineer-а, наиболее важные отличия от 32-битного x86 это:

\myindex{\CLanguageElements!\Pointers}
\begin{itemize}

\item
Почти все регистры (кроме FPU и SIMD) расширены до 64-бит и получили префикс R-. 
И еще 8 регистров добавлено. 
В итоге имеются эти \ac{GPR}-ы:
 \RAX, \RBX, \RCX, \RDX, 
\RBP, \RSP, \RSI, \RDI, \Reg{8}, \Reg{9}, \Reg{10}, 
\Reg{11}, \Reg{12}, \Reg{13}, \Reg{14}, \Reg{15}. 

К ним также можно обращаться так же, как и прежде. Например, для доступа к младшим 32 битам \RAX 
можно использовать \EAX:

\RegTableOne{RAX}{EAX}{AX}{AH}{AL}

У новых регистров \GTT{R8-R15} также имеются их \IT{младшие части}: \GTT{R8D-R15D} 
(младшие 32-битные части), 
\GTT{R8W-R15W} (младшие 16-битные части), \GTT{R8L-R15L} (младшие 8-битные части).

\RegTableFour{R8}{R8D}{R8W}{R8L}

Удвоено количество SIMD-регистров: с 8 до 16: \XMM{0}-\XMM{15}.

\item
В win64 передача всех параметров немного иная, это немного похоже на fastcall 
(\myref{fastcall}).
Первые 4 аргумента записываются в регистры \RCX, \RDX, \Reg{8}, \Reg{9}, а остальные ~--- в стек. 
Вызывающая функция также должна подготовить место из 32 байт чтобы вызываемая функция могла сохранить 
там первые 4 аргумента и использовать эти регистры по своему усмотрению. 
Короткие функции могут использовать аргументы прямо из регистров, но б\'{о}льшие функции могут сохранять 
их значения на будущее.

Соглашение System V AMD64 ABI (Linux, *BSD, \MacOSX)\SysVABI также напоминает
fastcall, использует 6 регистров 
\RDI, \RSI, \RDX, \RCX, \Reg{8}, \Reg{9} для первых шести аргументов.
Остальные передаются через стек.

См. также в соответствующем разделе о способах передачи аргументов через стек ~(\myref{sec:callingconventions}).

\item
\Tint в \CCpp остается 32-битным для совместимости.

\item
Все указатели теперь 64-битные.

\end{itemize}

\myindex{Register allocation}
Из-за того, что регистров общего пользования теперь вдвое больше, у компиляторов теперь больше 
свободного места для маневра, называемого \glslink{register allocator}{register allocation}.
Для нас это означает, что в итоговом коде будет меньше локальных переменных.

\myindex{DES}
Для примера, функция вычисляющая первый S-бокс алгоритма шифрования DES, 
она обрабатывает сразу 32/64/128/256 значений, в зависимости от типа \GTT{DES\_type} (uint32, uint64, SSE2 или AVX), 
методом bitslice DES (больше об этом методе читайте здесь~(\myref{bitslicedes})):

\lstinputlisting[style=customc]{patterns/20_x64/19_1.c}

Здесь много локальных переменных. Конечно, далеко не все они будут в локальном стеке. 
Компилируем обычным MSVC 2008 с опцией \GTT{/Ox}:

\lstinputlisting[caption=\Optimizing MSVC 2008,style=customasmx86]{patterns/20_x64/19_2_msvc_Ox.asm}

5 переменных компилятору пришлось разместить в локальном стеке.

Теперь попробуем то же самое только в 64-битной версии MSVC 2008:

\lstinputlisting[caption=\Optimizing MSVC 2008,style=customasmx86]{patterns/20_x64/19_3_msvc_x64.asm}

Компилятор ничего не выделил в локальном стеке, а \GTT{x36} это синоним для \GTT{a5}.

\iffalse
% FIXME1 невнятно
Кстати, видно, что функция сохраняет регистры \RCX, \RDX в отведенных для 
этого вызываемой функцией местах, 
а \Reg{8} и \Reg{9} не сохраняет, а начинает использовать их сразу.

\fi

Кстати, существуют процессоры с еще большим количеством \ac{GPR}, например, 
Itanium ~--- 128 регистров.

\subsection{ARM}

64-битные инструкции появились в ARMv8.

\subsection{Числа с плавающей запятой}

О том как происходит работа с числами с плавающей запятой в x86-64, читайте здесь: \myref{floating_SIMD}.

\subsection{Критика 64-битной архитектуры}

Некоторые люди иногда сетуют на то что указатели теперь 64-битные:
ведь теперь для хранения всех указателей нужно в 2 раза больше места 
в памяти, в т.ч. и в кэш-памяти, не смотря на то что x64-процессоры могут адресовать только 48 бит внешней \ac{RAM}.

\begin{framed}
\begin{quotation}
Pointers have gone out of favor to the point now where I had to
flame about it because on my 64-bit computer that I have here, if I really
care about using the capability of my machine I find that I’d better not use
pointers because I have a machine that has 64-bit registers but it only has 2
gigabytes of RAM. So a pointer never has more than 32 significant bits to it.
But every time I use a pointer it’s costing me 64 bits and that doubles the
size of my data structure. Worse, it goes into the cache and half of my
cache is gone and that costs cash—cache is expensive.

So if I’m really trying to push the envelope now, I have to use arrays instead
of pointers. I make complicated macros so that it looks like I’m using
pointers, but I’m not really.
\end{quotation}
\end{framed}

( Дональд Кнут в ``Coders at Work''. )

Некоторые люди делают свои аллокаторы памяти.
\myindex{CryptoMiniSat}
Интересен случай с CryptoMiniSat\footnote{\url{https://github.com/msoos/cryptominisat/}}.
Эта программа довольно редко использует более 4GiB памяти, но она очень активно использует указатели.
Так что, на 32-битной платформе она требовала меньше памяти, чем на 64-битной.
Чтобы справиться с этой проблемой, автор создал свой аллокатор (в файлах \IT{clauseallocator.(h|cpp)}),
который позволяет иметь доступ к выделенной памяти используя 32-битные идентификаторы вместо 64-битных указателей.

